
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/device.h>
#include <linux/io.h>
#include <linux/miscdevice.h>
#include <linux/uaccess.h>

#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>

static int LED_Major = 0;
static struct class *led_driver_class;
volatile unsigned long *GPBCON, *GPBDAT;


static int s3c24xx_led_open(struct inode *inode, struct file *file)
{
	printk("s3c24xx_led_open\n");
	(*GPBCON) |= 1<<2;
    return 0; 
}

static int s3c24xx_led_close(struct inode *inode, struct file *file)
{
	printk("s3c24xx_led_close\n");
    return 0; 
}

static int s3c24xx_led_write(struct file *file, char __user *buff, size_t count, loff_t *offp)
{
    int  value;
	
	copy_from_user(&value, buff, count);

	if(value == 1){
		(*GPBDAT) &= ~(1<<1);
	}else if(value == 0){
		(*GPBDAT) |= 1<<1;
	}else{
		printk("zhe writed value must be 1 or 0\n");
		return 1;
	}
    return 0;
}

static struct file_operations led_fops = {
    .owner   =   THIS_MODULE,
    .open    =   s3c24xx_led_open,
	.write	 =	 s3c24xx_led_write,
    .release =   s3c24xx_led_close,
};

static int __init led_init(void)
{
    LED_Major = register_chrdev(LED_Major, "led_driver", &led_fops);
	led_driver_class = class_create(THIS_MODULE, "led_driver");
	device_create(led_driver_class, NULL, MKDEV(LED_Major, 0), NULL, "led_driver");
	GPBCON = (volatile unsigned long*)ioremap(0x56000010,8);
	GPBDAT = GPBCON + 1;
	printk("led_init\n");
    return 0;
}

static void __exit led_exit(void)
{
    unregister_chrdev(LED_Major, "led_driver");
	device_destroy(led_driver_class, MKDEV(LED_Major, 0) );
	class_destroy(led_driver_class);
	iounmap(GPBCON);
	printk("led_exit\n");
}

module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("yuanlai");
MODULE_DESCRIPTION("helper2416 led Driver");
MODULE_LICENSE("GPL");
